Skip to content

Conversation

@m-aciek
Copy link

@m-aciek m-aciek commented Dec 20, 2025

Fixes #9015.

This PR introduces safe-datetime error code, which makes mypy check fail for unsafe date and datetime classes inheritance, following @JukkaL's comment in the related issue.

Before:

from datetime import date, datetime

if datetime.now() < date.today():  # passing the type checking
    print("that's a surprise!")

After:

from datetime import date, datetime

if datetime.now() < date.today():  # E: Unsupported operand types for < ("datetime" and "date")
    print("that's a surprise!")

This is Copilot agent's work with my prompts' guidance. I reviewed the produced code. The change includes tests and documentation.

Alternatives considered

PR history

  • first iteration was adding usafe-subtype code for other potential cases like date/datetime
  • I simplified the approach tackling only date/datetime case as others are being handled separately.

@github-actions

This comment has been minimized.

Copy link
Collaborator

@sterliakov sterliakov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding str vs Iterable[str]: are you sure it's actually a good thing to do? I hate pandas decision to prohibit passing a single string as DataFrame columns, it adds unnecessary friction to quickly creating a one-off dataframe (one has to do columns=list('abc')). Is there a reason to reject passing str as Iterable[str] intentionally? Is it a common source of bugs in some codebase you know/work with?

@m-aciek
Copy link
Author

m-aciek commented Dec 25, 2025

Thank you for the review, I will update and benchmark the list/set for this case tomorrow, having an access to the desktop computer.

Regarding str vs Iterable[str]: are you sure it's actually a good thing to do? I hate pandas decision to prohibit passing a single string as DataFrame columns, it adds unnecessary friction to quickly creating a one-off dataframe (one has to do columns=list('abc')). Is there a reason to reject passing str as Iterable[str] intentionally? Is it a common source of bugs in some codebase you know/work with?

It was originally suggested by @JukkaL and I thought it was a good idea. I personally at least once in the past experienced or seen a bug that could have been prevented with such a check.

But this makes me think that maybe a way to select an unsafe subtyping class may be a good addition, to offer better control for mypy users, to let use only one inheritance pair, instead of covering only all or none.

Co-authored-by: Stanislav Terliakov <[email protected]>
@github-actions

This comment has been minimized.

@m-aciek
Copy link
Author

m-aciek commented Jan 20, 2026

I'm sorry, it takes me more than I thought to get back to this PR. It looks like #20577 addresses the case of the Iterable[str]/str separately. Probably we can drop this case here.

I looked around for another cases of an unsafe subtyping, and the other one would be bool/int relation. I couldn't find more. I wonder if there shouldn't be separate mypy codes/flags for each of those two cases for a better control and user experience. What do you think @JukkaL @sterliakov ?

@m-aciek
Copy link
Author

m-aciek commented Jan 21, 2026

As discussed in the parent issue, I've updated the PR to focus only on datetime/date case, using safe-datetime code. @sterliakov would you find a spare moment for the review of the updated approach? Thank you.

@m-aciek m-aciek requested a review from sterliakov January 21, 2026 19:58
@github-actions
Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

datetimes and dates are not substitutable but mypy thinks they are

2 participants